package judesart.app.client.ui.admin.profile;

import java.util.ArrayList;
import java.util.Arrays;

import judesart.app.client.controller.ExhibitionController;
import judesart.app.client.controller.ExhibitionControllerAsync;
import judesart.app.client.model.CountryModel;
import judesart.app.client.widget.TopInfo;
import judesart.app.domain.Address;
import judesart.app.domain.Country;
import judesart.app.domain.Exhibition;

import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.Style.Scroll;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.FieldSetEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.Composite;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Dialog;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.TabItem;
import com.extjs.gxt.ui.client.widget.TabPanel;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.ComboBox;
import com.extjs.gxt.ui.client.widget.form.DateField;
import com.extjs.gxt.ui.client.widget.form.FieldSet;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.extjs.gxt.ui.client.widget.form.HtmlEditor;
import com.extjs.gxt.ui.client.widget.form.TextArea;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.form.ComboBox.TriggerAction;
import com.extjs.gxt.ui.client.widget.form.FormPanel.LabelAlign;
import com.extjs.gxt.ui.client.widget.layout.ColumnData;
import com.extjs.gxt.ui.client.widget.layout.ColumnLayout;
import com.extjs.gxt.ui.client.widget.layout.FormData;
import com.extjs.gxt.ui.client.widget.layout.FormLayout;
import com.google.appengine.api.datastore.Text;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class ExhibitionDetailPanel extends Composite {

    private FieldSet fldstBasic;
    private FieldSet fldstDetail;
    private FieldSet fldstGallery;
    private TextField<String> titleField;
    private HtmlEditor detailField;
    private DateField startDateField;
    private DateField endDateField;
    private TextField<String> curatorField;
    private TextArea artistField;
    private TextField<String> galleryNameField;
    private TextField<String> address1Field;
    private TextField<String> address2Field;
    private TextField<String> cityField;
    private TextField<String> regionField;
    private TextField<String> zipCodeField;
    private ComboBox<CountryModel> countryCombo;
    private Exhibition exhibition;
    private final ExhibitionControllerAsync controller = ExhibitionController.Util.getInstance();
    private final ExhibitionsPanel parent;
    private final TabItem tbtmPhotos;
    private final TabItem tbtmVideos;
    private final TabItem tbtmArtworks;
    private final ExhibitionPhotosPanel photosPanel;
    private final ExhibitionVideosPanel videosPanel;
    private final ExhibitionArtworksPanel artworksPanel;

    public ExhibitionDetailPanel(ExhibitionsPanel parent) {
        this.parent = parent;
        ContentPanel mainPanel = new ContentPanel();
        mainPanel.setHeading("Exhibition");
        mainPanel.setFrame(true);
        mainPanel.setSize(800, 513);

        TabPanel tabPanel = new TabPanel();
        tabPanel.setSize(785, 500);
        tabPanel.setBorders(false);
        tabPanel.setBodyBorder(false);

        TabItem tbtmBasicInfo = new TabItem("Basic Info");
        tbtmBasicInfo.add(createBasicInfoPanel());
        tabPanel.add(tbtmBasicInfo);

        tbtmPhotos = new TabItem("Photos");
        tbtmPhotos.setEnabled(false);
        photosPanel = new ExhibitionPhotosPanel(this);
        tbtmPhotos.add(photosPanel);
        tabPanel.add(tbtmPhotos);

        tbtmVideos = new TabItem("Videos");
        tbtmVideos.setEnabled(false);
        videosPanel = new ExhibitionVideosPanel(this);
        tbtmVideos.add(videosPanel);
        tabPanel.add(tbtmVideos);

        tbtmArtworks = new TabItem("Artworks");
        tbtmArtworks.setEnabled(false);
        artworksPanel = new ExhibitionArtworksPanel(this);
        tbtmArtworks.add(artworksPanel);
        tabPanel.add(tbtmArtworks);

        mainPanel.add(tabPanel);

        initComponent(mainPanel);
    }

    private FormPanel createBasicInfoPanel() {
        FormPanel formPanel = new FormPanel();
        formPanel.setFrame(true);
        formPanel.setLabelSeparator("");
        formPanel.setLabelAlign(LabelAlign.TOP);
        formPanel.setButtonAlign(HorizontalAlignment.CENTER);
        formPanel.setHeaderVisible(false);
        formPanel.setScrollMode(Scroll.AUTO);
        formPanel.setSize(785, 448);
        formPanel.setBorders(false);
        formPanel.setBodyBorder(false);

        fldstBasic = buildFieldSet("Basic");
        fldstBasic.setExpanded(true);

        titleField = new TextField<String>();
        titleField.setFieldLabel("Title");
        fldstBasic.add(titleField, new FormData("100%"));

        detailField = new HtmlEditor();
        detailField.setFieldLabel("Description");
        detailField.setHeight(200);
        fldstBasic.add(detailField, new FormData("100%"));

        formPanel.add(fldstBasic, new FormData("97%"));

        fldstDetail = buildFieldSet("Detail");
        fldstDetail.setExpanded(false);

        LayoutContainer left = new LayoutContainer();
        LayoutContainer right = new LayoutContainer();

        startDateField = new DateField();
        startDateField.setFieldLabel("Start Date");
        startDateField.setWidth(200);
        left.add(startDateField);

        endDateField = new DateField();
        endDateField.setFieldLabel("End Date");
        endDateField.setWidth(200);
        right.add(endDateField);

        fldstDetail.add(buildColumns(left, right), new FormData("100%"));

        curatorField = new TextField<String>();
        curatorField.setFieldLabel("Curator");
        fldstDetail.add(curatorField, new FormData("100%"));

        artistField = new TextArea();
        artistField.setFieldLabel("Other Artists");
        artistField.setHeight(100);
        fldstDetail.add(artistField, new FormData("100%"));

        formPanel.add(fldstDetail, new FormData("97%"));

        fldstGallery = buildFieldSet("Gallery");
        fldstGallery.setExpanded(false);

        galleryNameField = new TextField<String>();
        galleryNameField.setFieldLabel("Gallery Name");
        fldstGallery.add(galleryNameField, new FormData("100%"));

        buildAddress(fldstGallery);

        formPanel.add(fldstGallery, new FormData("97%"));

        Button btnSave = new Button("Save");
        btnSave.addListener(Events.Select, new Listener<ButtonEvent>() {
            public void handleEvent(ButtonEvent e) {
                save();
            }
        });
        formPanel.addButton(btnSave);
        Button btnDelete = new Button("Delete");
        btnDelete.addListener(Events.Select, new Listener<ButtonEvent>() {
            public void handleEvent(ButtonEvent e) {
                delete();
            }
        });
        formPanel.addButton(btnDelete);
        Button btnCancel = new Button("Cancel");
        btnCancel.addListener(Events.Select, new Listener<ButtonEvent>() {
            public void handleEvent(ButtonEvent e) {
                cancel();
            }
        });
        formPanel.addButton(btnCancel);
        return formPanel;
    }

    private void cancel() {
        parent.list();
    }

    private void delete() {
        Dialog d = new Dialog();
        d.setHeading("Confirm Delete");
        d.addText("Are you sure you want to delete this Exhibition?");
        d.setBodyStyle("font-weight:bold;padding:13px;text-align:center;");
        d.setSize(350, 110);
        d.setHideOnButtonClick(true);
        d.setButtons(Dialog.YESNO);
        d.getButtonById(Dialog.YES).addSelectionListener(
                new SelectionListener<ButtonEvent>() {

                    @Override
                    public void componentSelected(ButtonEvent ce) {
                        if (exhibition.getId() == null) {
                            cancel();
                            return;
                        }
                        callDeleteAsync();
                    }

                });
        d.show();
    }

    private void callDeleteAsync() {
        controller.deleteExhibition(exhibition.getId(),
                new AsyncCallback<Void>() {
                    @Override
                    public void onFailure(Throwable caught) {
                        TopInfo.display("Error", "Unable to delete Exhibition");
                    }

                    @Override
                    public void onSuccess(Void result) {
                        TopInfo.display("Info", "Exhibition deleted");
                        cancel();
                    }
                });
    }

    private void save() {
        bindToModel();
        if (exhibition.getId() == null) {
            callCreateExhibitionAsync();
        } else {
            callUpdateExhibitionAsync();
        }
    }

    private void callUpdateExhibitionAsync() {
        controller.updateExhibition(exhibition,
                new AsyncCallback<Exhibition>() {

                    @Override
                    public void onSuccess(Exhibition result) {
                        exhibition = result;
                        TopInfo.display("Info", "Exhibition updated.");
                        bindToForm();
                    }

                    @Override
                    public void onFailure(Throwable caught) {
                        TopInfo.display("Error", "Unable to create Exhibition.");
                    }
                });
    }

    private void callCreateExhibitionAsync() {
        controller.createExhibition(exhibition,
                new AsyncCallback<Exhibition>() {

                    @Override
                    public void onSuccess(Exhibition result) {
                        exhibition = result;
                        TopInfo.display("Info", "Exhibition created.");
                        bindToForm();
                    }

                    @Override
                    public void onFailure(Throwable caught) {
                        TopInfo.display("Error", "Unable to create Exhibition.");
                    }
                });
    }

    private void bindToModel() {
        exhibition.setTitle(titleField.getValue());
        exhibition.setDetail(new Text(detailField.getValue()));
        exhibition.setStartDate(startDateField.getValue());
        exhibition.setEndDate(endDateField.getValue());
        exhibition.setCurator(curatorField.getValue());
        String artists = artistField.getValue();
        if (exhibition.getExhibitingArtists() == null) {
            exhibition.setExhibitingArtists(new ArrayList<String>());
        }
        exhibition.getExhibitingArtists().clear();
        if (artists != null && artists.trim().length() > 0) {
            String[] all = artists.split("[,;\\n]");
            exhibition.getExhibitingArtists().addAll(Arrays.asList(all));
        }
        exhibition.setGalleryName(galleryNameField.getValue());
        if (exhibition.getGalleryAddress() == null)
            exhibition.setGalleryAddress(new Address());
        Address address = exhibition.getGalleryAddress();
        address.setAddress1(address1Field.getValue());
        address.setAddress2(address2Field.getValue());
        address.setCity(cityField.getValue());
        address.setPostalCode(zipCodeField.getValue());
        if (countryCombo.getValue() != null) {
            address.setCountry(countryCombo.getValue().getCountry());
        } else {
            address.setCountry(Country.NOT_SET);
        }
    }

    private void bindToForm() {
        titleField.setValue(exhibition.getTitle());
        if (exhibition.getDetail() != null)
            detailField.setValue(exhibition.getDetail().getValue());
        else
            detailField.setValue(null);
        startDateField.setValue(exhibition.getStartDate());
        endDateField.setValue(exhibition.getEndDate());
        curatorField.setValue(exhibition.getCurator());
        String artists = "";
        if (exhibition.getExhibitingArtists() != null) {
            for (String artist : exhibition.getExhibitingArtists()) {
                artists += artist + "\n";
            }
            artistField.setValue(artists);
        }
        artistField.setValue(artists);
        galleryNameField.setValue(exhibition.getGalleryName());
        Address address = exhibition.getGalleryAddress();
        if (address != null) {
            address1Field.setValue(address.getAddress1());
            address2Field.setValue(address.getAddress2());
            cityField.setValue(address.getCity());
            zipCodeField.setValue(address.getPostalCode());
            if (address.getCountry() != null) {
                countryCombo.setValue(new CountryModel(address.getCountry()));
            } else {
                countryCombo.setValue(null);
            }
        } else {
            address1Field.setValue(null);
            address2Field.setValue(null);
            cityField.setValue(null);
            zipCodeField.setValue(null);
            countryCombo.setValue(null);
        }
        boolean isNew = exhibition.getId() == null;
        tbtmPhotos.setEnabled(!isNew);
        tbtmVideos.setEnabled(!isNew);
        tbtmArtworks.setEnabled(!isNew);
        photosPanel.refresh();
        videosPanel.refresh();
        artworksPanel.refresh();
    }

    private LayoutContainer buildColumns(LayoutContainer left,
            LayoutContainer right) {
        LayoutContainer main = new LayoutContainer();
        main.setLayout(new ColumnLayout());

        left.setStyleAttribute("paddingRight", "10px");
        left.setLayout(createFormLayout());

        right.setStyleAttribute("paddingLeft", "10px");
        right.setLayout(createFormLayout());
        main.add(left, new ColumnData(.5));
        main.add(right, new ColumnData(.5));
        return main;
    }

    private FormLayout createFormLayout() {
        FormLayout layoutl = new FormLayout();
        layoutl.setLabelAlign(LabelAlign.TOP);
        layoutl.setLabelSeparator("");
        return layoutl;
    }

    private void buildAddress(FieldSet addressFieldSet) {

        address1Field = new TextField<String>();
        address1Field.setFieldLabel("Street Address 1");
        addressFieldSet.add(address1Field, new FormData("100%"));

        address2Field = new TextField<String>();
        address2Field.setFieldLabel("Street Address 2");
        addressFieldSet.add(address2Field, new FormData("100%"));

        LayoutContainer main = new LayoutContainer();
        main.setLayout(new ColumnLayout());

        FormLayout layoutl = createFormLayout();
        LayoutContainer left = new LayoutContainer();
        left.setStyleAttribute("paddingRight", "10px");
        left.setLayout(layoutl);

        LayoutContainer right = new LayoutContainer();
        right.setStyleAttribute("paddingLeft", "10px");
        FormLayout layoutr = createFormLayout();
        right.setLayout(layoutr);

        cityField = new TextField<String>();
        cityField.setFieldLabel("City");
        left.add(cityField, new FormData("100%"));
        cityField.setName("address.city");

        regionField = new TextField<String>();
        regionField.setFieldLabel("Region");
        right.add(regionField, new FormData("100%"));

        zipCodeField = new TextField<String>();
        zipCodeField.setFieldLabel("Zip Code");
        left.add(zipCodeField, new FormData("100%"));

        ListStore<CountryModel> store = new ListStore<CountryModel>();
        store.add(CountryModel.getCountries());

        countryCombo = new ComboBox<CountryModel>();
        countryCombo.setFieldLabel("Country");
        countryCombo.setDisplayField("title");
        countryCombo.setTriggerAction(TriggerAction.ALL);
        countryCombo.setStore(store);
        countryCombo.setForceSelection(true);
        right.add(countryCombo, new FormData("100%"));

        main.add(left, new ColumnData(.5));
        main.add(right, new ColumnData(.5));
        addressFieldSet.add(main, new FormData("100%"));
    }

    private void fieldSetExpand(FieldSetEvent e) {
        FieldSet fsToExpand = e.getFieldSet();
        if (fsToExpand != fldstBasic) {
            fldstBasic.setExpanded(false);
        }
        if (fsToExpand != fldstDetail) {
            fldstDetail.setExpanded(false);
        }
        if (fsToExpand != fldstGallery) {
            fldstGallery.setExpanded(false);
        }
    }

    public void open(Long exhibitionId) {
        if (exhibitionId == null) {
            exhibition = new Exhibition();
            bindToForm();
        } else {
            controller.getExhibition(exhibitionId,
                    new AsyncCallback<Exhibition>() {
                        @Override
                        public void onFailure(Throwable caught) {
                            TopInfo.display("Error",
                                    "Unable to open exhibition");
                        }

                        @Override
                        public void onSuccess(Exhibition result) {
                            exhibition = result;
                            bindToForm();
                        }
                    });
        }
    }

    private FieldSet buildFieldSet(String heading) {
        FieldSet fldstBasic = new FieldSet();
        fldstBasic.setHeading(heading);
        fldstBasic.setCollapsible(true);
        fldstBasic.addListener(Events.BeforeExpand,
                new Listener<FieldSetEvent>() {
                    public void handleEvent(FieldSetEvent e) {
                        fieldSetExpand(e);
                    }
                });
        FormLayout flFldstBasic = new FormLayout();
        flFldstBasic.setLabelSeparator("");
        flFldstBasic.setLabelAlign(LabelAlign.TOP);
        flFldstBasic.setDefaultWidth(700);
        fldstBasic.setLayout(flFldstBasic);
        return fldstBasic;
    }

    Exhibition getExhibition() {
        return exhibition;
    }
}
